package sketch.ast;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.internal.core.dom.NaiveASTFlattener;

public class HoleExtractionVisitor extends NaiveASTFlattener {
	
	static int hole_count = 0;

	//this visit transforms an AST to an AST with holes
	public final MethodDeclaration transformed_method;
	
	public final Map<MethodInvocation, GeneratorHole> invocationHoleMap
	    = new LinkedHashMap<MethodInvocation, GeneratorHole>();
	
	public final Map<MethodInvocation, Expression> invocationReceiverMap
	    = new LinkedHashMap<MethodInvocation, Expression>();
	
	public final Set<Statement> removeStatements = new LinkedHashSet<Statement>();
	
	public HoleExtractionVisitor(MethodDeclaration method) {
		this.transformed_method = method;
	}
	
	public MethodDeclarationWithHoles getTransformedMethod() {
		return new MethodDeclarationWithHoles(transformed_method, invocationHoleMap, invocationReceiverMap,
				removeStatements);
	}
	
	@Override
	public boolean visit(VariableDeclarationStatement statement) {
		if(statement.toString().indexOf("ValueGenerator<") != -1) {
			this.removeStatements.add(statement);
			return false;
		}
		return true;
	}
	
	@Override
	public boolean visit(MethodInvocation methodInvoke) {
		if(ASTUtils.isGeneratorInvocation(methodInvoke)) {
		  //System.out.println("Find a method invocation: " + methodInvoke.toString());
		  GeneratorHole hole = new GeneratorHole();
		  hole.content = (hole_count++) + ". " + hole.content;
		  invocationHoleMap.put(methodInvoke, hole);
		  
		  Expression expr = ASTUtils.extractReceiverExpr(methodInvoke);
		  invocationReceiverMap.put(methodInvoke, expr);
		  
		  return false;
		}
		return true;
	}
	
}